package com.jlg.util;

import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.Date;

import com.jlg.beans.page.Content;

/**
 * 
 * author: huazhang
 * since : 2011-3-15
 */
public class GoogleMapUtil
{
    private static final double EARTH_RADIUS = 6378.137;
    private static boolean allowVisitGoogleMap = true;
    private static Date lastVisitTime = new Date();
    
    public static void main(String[] args)
    {
        String result = queryGeographicInfoByGoogleMap("北京"); // 200,4,31.2303930,121.4737040
        System.out.println(GoogleMapUtil.computerPrecisionDistance(31.2303930,121.4737040,39.9042140,116.4074130)); 
        System.out.println(GoogleMapUtil.computerDistance(31.2303930,121.4737040,39.9042140,116.4074130)); 
        System.out.println(result);
    }
    
    /**
     * 利用googlemap api 通过 HTTP 进行地址解析
     * http://code.google.com/intl/en/apis/maps/documentation/javascript/v2/services.html#Geocoding_Direct
     * http://code.google.com/intl/zh-CN/apis/maps/signup.html
     * @param address 地址
     * @return HTTP状态代码,精度常量,纬度,经度. 例：200,4,31.2303930,121.4737040
     * 注意： 如果24小时内从一个 IP 地址收到的地址解析请求数超过 2500 个，或从一个 IP 地址提交的地址解析请求速度过快，则 Google Maps API 地址解析器将会开始以620状态代码作为响应。
     */
    public static String queryGeographicInfoByGoogleMap(String address)
    {
        try
        {
            String result = null;
            Date now = new Date();
            long del = (now.getTime() - lastVisitTime.getTime()) / 3600 / 1000;
            if (!allowVisitGoogleMap && del <= 24)
            {
                return null;
            }
            allowVisitGoogleMap = true;
            Thread.sleep(1000);
            
            address = URLEncoder.encode(address, "UTF-8");
            String[] arr = new String[4];
            arr[0] = address;
            arr[1] = "csv";
            arr[2] = "true";
            arr[3] = "ABQIAAAAGc98g4eLSQPmkk-lnGuqlBRhfL5nBoRWZWqlN2LjYR2uDldNxRTiufOj-YMckY1qirrsx3II5szs-g"; // ABQIAAAAzr2EBOXUKnm_jVnk0OJI7xSosDVG8KKPE1-m51RBrvYughuyMxQ-i1QfUnH94QxWIa6N4U6MouMmBA
            // http://maps.google.com/maps/geo?q=Chicago&output=cvs&key=ABQIAAAAzr2EBOXUKnm_jVnk0OJI7xSosDVG8KKPE1-m51RBrvYughuyMxQ-i1QfUnH94QxWIa6N4U6MouMmBA
            String url = MessageFormat.format("http://maps.google.com/maps/geo?q={0}&output={1}&sensor={2}&key={3}",arr);
            Content content = HttpUtil.GetContent(url,"UTF-8", false);
            if(content!=null)
            {
                result = new String(content.getContent(), content.getEncoding());
                if (result != null && result.startsWith("620"))
                {
                    allowVisitGoogleMap = false;
                    lastVisitTime = new Date();
                }
            }
            return result;
        } catch (Exception e)
        {
            e.printStackTrace();
            return null;
        }
    }
    
   
    private static double rad(double d)
    {
        return d * Math.PI / 180.0;
    }

    /**
     * 已知两个地点经纬度算距离(高精度）
     */
    public static double computerDistance(double lat1, double lng1, double lat2,
            double lng2)
    {
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double a = radLat1 - radLat2;
        double b = rad(lng1) - rad(lng2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
                + Math.cos(radLat1) * Math.cos(radLat2)
                * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;
        s = Math.round(s * 10000) / 10000;
        return s;
    }

    /**
     * 已知两个地点经纬度算距离(高精度）
     */
    public static double computerPrecisionDistance(double wd1, double jd1, double wd2, double jd2)
    {
        double x, y, out;
        double PI = 3.14159265;
        double R = 6.371229 * 1e6;
        x = (jd2 - jd1) * PI * R * Math.cos(((wd1 + wd2) / 2) * PI / 180) / 180;
        y = (wd2 - wd1) * PI * R / 180;
        out = Math.hypot(x, y);
        return out / 1000;
    }

}
